﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SKUID_Parse
{
    public partial class frmSkuidParse : Form
    {
        #region Private Properties
        // CSV Field Mappings
        private Dictionary<string, int> _mappings = new Dictionary<string, int>()
         { 
             { "Id", 0 },
             { "Name", 1 },
             { "skuid__Module__c", 2},
             { "skuid__Type__c", 3 },
             { "skuid__UniqueId__c", 4 },
             { "OwnerId", 5 },
             { "Owner.Name", 6 },
             { "CreatedById", 7 },
             { "CreatedBy.Name", 8 },
             { "skuid__Layout__c", 9 },
             { "skuid__Layout2__c", 10 },
             { "skuid__Layout3__c", 11 },
             { "skuid__Layout4__c", 12 },
             { "skuid__Layout5__c", 13 }
         };
        #endregion

        #region cstor
        public frmSkuidParse()
        {
            InitializeComponent();
        }
        #endregion

        #region Form Event Handlers
        private void btnSource_Click(object sender, EventArgs e)
        {
            ofdSource.InitialDirectory = GetDownloadsPath();
            ofdSource.RestoreDirectory = true;
            if (ofdSource.ShowDialog() == DialogResult.OK)
            {
                tbSource.Text = ofdSource.FileName;
            }
        }

        private void btnDestination_Click(object sender, EventArgs e)
        {
            if (fbdDestination.ShowDialog() == DialogResult.OK)
            {
                tbDestination.Text = fbdDestination.SelectedPath;
            }
        }

        private void btnParse_Click(object sender, EventArgs e)
        {
            if (!File.Exists(tbSource.Text))
            {
                MessageBox.Show("Source file does not exist.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (!Directory.Exists(tbDestination.Text))
            {
                MessageBox.Show("Destination does not exist.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                StreamReader reader = new StreamReader(tbSource.Text);
                string[] lineDelimiter = { Environment.NewLine };
                string[] lines = reader.ReadToEnd().Split(lineDelimiter, StringSplitOptions.None);
                reader.Close();

                int pageCnt = 0;
                pbStatus.Value = 0;
                pbStatus.Visible = true;

                // Skip first line as its the field mappings
                for (int lineNum = 1; lineNum < lines.Count(); lineNum++)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine(lines[lineNum]);
                    try
                    {
                        while (!Regex.IsMatch(lines[lineNum + 1], "^a[a-zA-Z0-9]{17},"))
                        {
                            lineNum++;
                            sb.AppendLine(lines[lineNum]);
                        }
                    }
                    catch (IndexOutOfRangeException exc) { }

                    string[] fields = sb.ToString().Split(',');
                    if (cbSkuid.Checked || !fields[_mappings["Owner.Name"]].Equals("Skuid"))
                    {
                        StreamWriter writer = new StreamWriter(tbDestination.Text + "\\" + fields[_mappings["skuid__UniqueId__c"]] + ".xml", false, Encoding.UTF8);
                        writer.Write(Regex.Match(sb.ToString(), @"<skuidpage.+?<\/skuidpage>", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[0].Value);
                        writer.Close();

                        pageCnt++;
                    }

                    pbStatus.Value = Convert.ToInt32(Math.Round((Convert.ToDecimal(lineNum) / Convert.ToDecimal(lines.Count())) * 100));
                }

                pbStatus.Visible = false;

                MessageBox.Show("Processed: " + pageCnt.ToString() + " page(s).");
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion

        #region Private Methods
        private static string GetDownloadsPath()
        {
            string path = null;
            if (Environment.OSVersion.Version.Major >= 6)
            {
                IntPtr pathPtr;
                int hr = SHGetKnownFolderPath(ref FolderDownloads, 0, IntPtr.Zero, out pathPtr);
                if (hr == 0)
                {
                    path = Marshal.PtrToStringUni(pathPtr);
                    Marshal.FreeCoTaskMem(pathPtr);
                    return path;
                }
            }
            path = Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
            path = Path.Combine(path, "Downloads");
            return path;
        }

        private static Guid FolderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        private static extern int SHGetKnownFolderPath(ref Guid id, int flags, IntPtr token, out IntPtr path);
        #endregion
    }
}
